//
//  TQQShineLabel.swift
//  SwiftLearning
//  闪显闪隐
//  Created by 黄龙 on 2024/1/24.
//

import UIKit

class TQQShineLabel: UILabel {
    var shineDuration:CGFloat = 2.5
    var fadeoutDuration:CGFloat = 2.5
    var autoShine:Bool = false
    var isFadeOut:Bool = true
    var characterAnimationDurations:[CGFloat] = []
    var characterAnimationDelays:[CGFloat] = []
    var displaylink:CADisplayLink?
    var beginTime:CFTimeInterval = 0
    var endTime:CFTimeInterval = 0
    var attributedString:NSMutableAttributedString?

    var completion:os_block_t?
    
    override var text: String?{
        get{
            return super.text
        }
        set{
            if let text = newValue{
                self.attributedText = NSAttributedString(string: text)
            }else{
                self.attributedText = NSAttributedString(string: "the title is null,ha he")
            }
        }
    }
    
    override var attributedText: NSAttributedString?{
        get{
            return self.attributedString //或 =super.attributedText
        }
        set{
            if let theValue = newValue{
                self.attributedString = initialAttributedStringFromAttributedString(attributedString: theValue)
                super.attributedText = self.attributedString //是赋值给super.attributedText哦，不能赋给self.attributedText
                if let attributedText = super.attributedText{
                    self.characterAnimationDelays.removeAll()
                    self.characterAnimationDurations.removeAll()
                    for i in 0 ..< attributedText.length{
//获取每个字的显隐随机延迟时间及随机动画时间
                        self.characterAnimationDelays.append(CGFloat(arc4random_uniform(UInt32(self.shineDuration / 2.0 * 100.0))) / 100.0)
                        //arc4random_uniform(n)返回0~n(不包括n)的整数
                        let remain = self.shineDuration - self.characterAnimationDelays[i]
                        self.characterAnimationDurations.append(CGFloat(arc4random_uniform(UInt32(remain * 100.0))) / 100.0)
                    }
                }
            }
        }
    }
    
    func initialAttributedStringFromAttributedString(attributedString:NSAttributedString)->NSMutableAttributedString?{
//先将字体颜色置为不可见
        let mutableAttributedString:NSMutableAttributedString = attributedString.mutableCopy() as! NSMutableAttributedString
        let color = self.textColor.withAlphaComponent(0)
        mutableAttributedString.addAttribute(.foregroundColor, value: color, range: NSMakeRange(0, mutableAttributedString.length))
        return mutableAttributedString
    }
    
    init(frame:CGRect,title:String?){
        super.init(frame: frame)
        self.initUI(title)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func initUI(_ title:String?){
        self.textColor = .label
        self.font = UIFont.systemFont(ofSize: 16)
        self.numberOfLines = 0
        
        displaylink = CADisplayLink(target: self, selector: #selector(updateAttributedString))
        displaylink?.isPaused = true
        displaylink?.add(to:.current, forMode: .common)
        if let text = title{
            self.text = text
        }else{
            self.text = "the title is null,ha he"
        }
        NSLog("%@\n%@", self.text!,self.attributedText!)
    }
    
//2种开启shine的接口
    func shine(){
        shineWithCompletion(completion: nil)
    }
    
    func shineWithCompletion(completion:os_block_t?){
        if (!self.isShining() && isFadeOut){
            self.completion = completion
            self.isFadeOut = false
            startAnimationWithDuration(duration: self.shineDuration)
        }
    }
    
//2种将文字渐隐掉的方法
    func fadeOut(){
        fadeOutWithCompletion(completion: nil)
    }
    
    func fadeOutWithCompletion(completion:os_block_t?){
        if(!isShining() && !isFadeOut){
            self.completion = completion
            self.isFadeOut = true
            startAnimationWithDuration(duration: self.fadeoutDuration)
        }
    }
    
    func isVisible()->Bool{
        return !self.isFadeOut
    }
    
    func isShining()->Bool{
        if let displaylink = self.displaylink{
            return !displaylink.isPaused
        }
        return false
    }
}

extension TQQShineLabel{
    @objc func updateAttributedString(){
//文字闪烁效果具体的实现
        let now = CACurrentMediaTime()
        if let attributedString = self.attributedString{
            for i in 0 ..< attributedString.length{
                if (CharacterSet.whitespacesAndNewlines as NSCharacterSet).characterIsMember((attributedString.string as NSString).character(at: i)){
                    continue
                }
                attributedString.enumerateAttribute(.foregroundColor, in: NSMakeRange(i, 1),options: .longestEffectiveRangeNotRequired) { value, range, stop in
                    let currentAlpha = (value as! UIColor).cgColor.alpha
                    let shouldUpdateAlpha = (self.isFadeOut && (currentAlpha > 0)) || (!self.isFadeOut && currentAlpha<1) || ((now - self.beginTime) >= self.characterAnimationDelays[i])
//alpha>0且标记为消隐(fadeout)，或者未标记为消隐且alpha<1(shine),或delaytime已到时
                    if !shouldUpdateAlpha{
                        return
                    }
                    
                    var percentage = (now - self.beginTime - self.characterAnimationDelays[i]) / self.characterAnimationDurations[i]
                    if (self.isFadeOut){
                        percentage = 1 - percentage
                    }
                    NSLog("percentage = %.2f", percentage)
                    let color = self.textColor.withAlphaComponent(percentage)
                    attributedString.addAttribute(.foregroundColor, value: color, range: range)
                }
            }
        }
        super.attributedText = self.attributedString
        if (now > self.endTime){
            self.displaylink?.isPaused = true
            if let completion = self.completion{
                completion()
            }
        }
    }

    private func startAnimationWithDuration(duration:CFTimeInterval){
        self.beginTime = CACurrentMediaTime()
        self.endTime = self.beginTime + self.shineDuration
        self.displaylink?.isPaused = false
    }

}
